Fail the job when altool rejects an upload - #3
Merged
Conversation
distribute-beta and distribute-release reported green jobs on failed App Store uploads. On LeanBytes/framebison two consecutive betas never reached TestFlight while both runs went green; the only way to see it was reading the raw altool log. The benign-case guard was meant to tolerate a genuine redundant upload — same version and build already on ASC, which Apple reports as ITMS-90189. It matched on "already been (used|uploaded)". Apple phrases the build number collision as "an attribute with a value that has already been used (-19232) The bundle version must be higher than the previously uploaded version", so a real failure needing a higher CFBundleVersion hit the same branch and was treated as an idempotent re-run. RC was captured from altool and never checked, leaving the decision purely textual. Narrow the benign pattern to ITMS-90189 / "redundant binary upload", and accept RC == 0 up front so a success with unexpected wording is not misread as a failure. The logic was duplicated inline in both workflows, which is how one defect came to exist in two places, so extract it as classify_upload in .github/scripts/classify-upload.sh and source it from each. tests/run.sh covers the three outcomes against real altool output, sourcing the shipped script so the test cannot drift from what runs. The collision case is verbatim from the run that shipped green. Closes #2
This was referenced Aug 6, 2026
sarensw
added a commit
that referenced
this pull request
Aug 6, 2026
selftest was the last ubuntu-latest job in the repo, and also the only workflow that stopped dispatching: no run for PRs #3 or #5, none for either merge to main, zero check runs created, and reopening a PR to re-fire pull_request changed nothing. Every self-hosted job kept running throughout. GitHub-hosted runners are a separate capacity and billing path from our own, so a block there takes out exactly this job and nothing else. The correlation is one-to-one: the only hosted job is the only broken one. Nothing here needs Linux — actionlint ships a darwin build and the tests are offline python3 plus git. Install actionlint into RUNNER_TEMP rather than the workspace. A self-hosted runner reuses its checkout, so ./actionlint would otherwise sit untracked in the working tree between runs. Also drop two comments left stale by v0.4.7, which moved every job to self-hosted but kept describing the prepare jobs as running on ubuntu. Comment-only, so callers are unaffected and no new tag is needed; selftest is not a reusable workflow, so no pin changes either. Closes #6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
distribute-betaanddistribute-releasereported green jobs on failed App Store uploads. On LeanBytes/framebison two consecutive betas never reached TestFlight while both runs went green — the only way to see it was reading the raw altool log.The bug
The benign-case guard was meant to tolerate a genuine redundant upload (same version and build already on ASC,
ITMS-90189). It matched onalready been (used|uploaded). Apple phrases the build-number collision as:Same branch. So a real failure needing a higher
CFBundleVersionwas treated as an idempotent re-run.RCwas captured from altool and never checked, leaving the decision purely textual.The fix
ITMS-90189/redundant binary upload.RC == 0up front, so a success with unexpected wording isn't misread as a failure.classify_uploadinto.github/scripts/classify-upload.sh. The logic was duplicated inline in both workflows — which is precisely how one defect came to exist in two places. Both publish jobs already check out.shared-ci, so this adds no new plumbing.tests/run.sh, sourcing the shipped script rather than re-implementing it, so the test can't drift from what actually runs.Behaviour change
UPLOAD SUCCEEDED-19232build-number collisionITMS-90189redundant uploadTwo rows change. The third is the reported bug; the second is a false-negative fixed in passing.
Verification
The collision fixture is verbatim from the framebison run that shipped green.
actionlintclean with the same ignoresselftest.ymluses.Note for reviewers
This is a behaviour change for every product on
v0.4.x: uploads that previously passed silently will now fail the job. That's the point — but if any product has been relying on the old leniency, its next release will start failing. I'd expect that only where a build number is genuinely colliding, which is a bug in that product.Not merged — left for review. Needs a version tag (
v0.4.9) to reach callers, since they pin@v0.4.8.Closes #2